package com.jyhz.gateway.config;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.jyhz.author.common.pojo.UserInfo;
import com.jyhz.author.common.utils.JwtUtils;
import com.jyhz.common.dto.HttpResult;
import com.jyhz.common.util.HttpStatusCode;
import com.jyhz.common.util.TimeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Objects;

/**
 * @author:谢君臣
 * @Date:2021/6/15-18:57
 * @version:1.0
 * @function:
 */

@Configuration
public class GlobalFilterconfig implements GlobalFilter, Ordered {

    private final PathFilterConfig pathFilter;

    private final JwtProperties JwtProperties;

    private Logger logger = LoggerFactory.getLogger("路由层全局过滤器");
    // 定义一个线程域，存放登录用户
    private static final ThreadLocal<UserInfo> tl = new ThreadLocal<>();

    public GlobalFilterconfig(JwtProperties JwtProperties, PathFilterConfig pathFilter) {
        this.JwtProperties = JwtProperties;
        this.pathFilter = pathFilter;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        HashSet<String> whitePaths = pathFilter.getWhitepaths();
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        if (!whitePaths.contains(path)){ // 判断路径是否在白名单,否则需要鉴权
            try {
                String token = Objects.requireNonNull(request.getCookies().getFirst("JYHZ_TOKEN")).getValue();
                if (StringUtils.isBlank(token)) {
                    // 未登录,返回401
                    ServerHttpResponse response = exchange.getResponse();
                    return out(response);
                }
                // 有token，查询用户信息
                // 解析成功，证明已经登录
                UserInfo user = JwtUtils.getInfoFromToken(token, JwtProperties.getPublicKey());
                // 放入线程域
                tl.set(user);
            } catch (Exception e) {
                // 抛出异常，证明未登录或超时,返回401
                ServerHttpResponse response = exchange.getResponse();
                return out(response);
            }
        }
        // 放行: 使用过滤器链，将请求继续向下传递
        return chain.filter(exchange);
    }
    // 定义当前过滤器的优先级。值越小，优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
    // 使用webflux输入请求信息
    private Mono<Void> out(ServerHttpResponse response) {

        HttpResult result = new HttpResult(
                HttpStatusCode.UNAUTHORIZED.getCode(),
                HttpStatusCode.UNAUTHORIZED.getEnMessage(),
                HttpStatusCode.UNAUTHORIZED.getZhMessage(),
                TimeUtils.nowStr(TimeUtils.DEF_FMT_DATE_TIME));
        byte[] bytes = JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        // 指定编码，否则在浏览器中会中文乱码
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        // 输出http响应
        return response.writeWith(Mono.just(buffer));
    }

}
